package NG::Sys::App;
use strict;
use warnings;
use utf8;

require NG::Sys::App::Add;
our @ISA = qw(NG::Sys::App::Add);

use Extend;
our @EXPORT = qw(app);

use NG::Sys::Cfg;
use Data::Dumper;
use Time::HiRes qw(gettimeofday);

our $app;
sub app {
	return $app;
}
sub new {
    my ($class,%args) = @_;
    my $self = $app = bless \%args, Class;
	$self->{cfg} = config($self->{config});
	for my $cfg (((map {config($_)} @{$self->{config_list}||[]}),appconfig($self->script))){
		while(my($k,$v) = each %$cfg){
			$self->{$k} = $v;
		}
	}
	$self->{persist} = {};
	$self->{context} = {};
    return $self;
}
sub fullscript {
	my ($self) = @_;
	return $self->{fullscript} ||= ($ENV{SCRIPT_FILENAME} || Cwd::realpath($0));
}
sub script {
	my ($self) = @_;
	my $ret;
	unless($ret = $self->{script}){
		( $self->{script} = $self->fullscript ) =~ s|.*/||;
		return $self->{script};
	}else{
		return $ret;
	}
}
sub get_persist {
	my ($self,$c) = @_;
	return $self->{persist}{$c} ||= {};
}
sub drop_persist {
	my ($self) = @_;
	$self->{persist} = {};
}
sub get_context {
	my ($self,$c) = @_;
	return $self->{context}{$c} ||= {};
}
sub drop_context {
	my ($self) = @_;
	$self->{context} = {};
}
sub mark_time {
	my $self = shift;
	my $label = shift;
	my $depth = shift;
	my $no_time = shift;
	unless(defined $depth){
		$depth = -1;
	}
	my $c = $self->get_context("timestamp");
	my $now;
	my $ary = ($c->{$label} ||= []);
	my $last = @$ary;
	
	unless($no_time){
		$now = scalar gettimeofday();
		push @$ary,$now;
	}elsif($last){
		$now = $ary->[$last - 1];
	}else{
		die "cannot get empty makr time for $label";
	}
	
	if($depth < 0){
		$depth += $last;
	}
	if($depth < 0 or $last <= $depth){
		return 0;
	}
	return $now - $ary->[$depth];
}
sub ext_warn {
	my ($self,$sub) = @_;
	require Carp;
	my $pkg = ref $self;
	unless($sub or $sub = $pkg->can("spec_warn")){
		$sub = \&Carp::cluck;
	}
	$SIG{__WARN__} = $sub;
	*CORE::GLOBAL::warn = $sub;
}
#sub spec_warn {
#	#Carp::longmess(@_);
#	Carp::cluck(@_);
#}
sub ext_die {
	my ($self,$sub) = @_;
	require Carp;
	my $pkg = ref $self;
	unless($sub or $sub = $pkg->can("spec_die")){
		$sub = \&Carp::confess;
	}
	$Carp::CarpInternal{'NG::Sys::DB::myDBI::st'}++;
	$Carp::CarpInternal{'NG::Sys::App::Cgi'}++;
	$Carp::CarpInternal{'NG::Sys::App'}++;
	*CORE::GLOBAL::die = $sub;
	$SIG{__DIE__} = $sub;
}
#sub spec_die{
#	Carp::confess(@_);
#}
sub __i {
	1 if *CORE::GLOBAL::die && *CORE::GLOBAL::warn;
}
1;
